package org.linlinjava.litemall.wx.web;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.linlinjava.litemall.core.notify.NotifyService;
import org.linlinjava.litemall.core.notify.NotifyType;
import org.linlinjava.litemall.core.util.CharUtil;
import org.linlinjava.litemall.core.util.JacksonUtil;
import org.linlinjava.litemall.core.util.RegexUtil;
import org.linlinjava.litemall.core.util.ResponseUtil;
import org.linlinjava.litemall.core.util.bcrypt.BCryptPasswordEncoder;
import org.linlinjava.litemall.db.domain.LitemallMessage;
import org.linlinjava.litemall.db.domain.LitemallUser;
import org.linlinjava.litemall.db.domainVo.MessageVo;
import org.linlinjava.litemall.db.service.CouponAssignService;
import org.linlinjava.litemall.db.service.LitemallMessageService;
import org.linlinjava.litemall.db.service.LitemallUserService;
import org.linlinjava.litemall.wx.GeneratorUUIDKits.GeneratorUIDTools;
import org.linlinjava.litemall.wx.annotation.LoginUser;
import org.linlinjava.litemall.wx.dao.UserInfo;
import org.linlinjava.litemall.wx.dao.UserToken;
import org.linlinjava.litemall.wx.dao.WxLoginInfo;
import org.linlinjava.litemall.wx.service.CaptchaCodeManager;
import org.linlinjava.litemall.wx.service.UserTokenManager;
import org.linlinjava.litemall.wx.util.IpUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static org.linlinjava.litemall.wx.util.WxResponseCode.*;

/**
 * 鉴权服务
 */
@RestController
@RequestMapping("/wx/auth")
@Validated
public class WxAuthController {
    private final Log logger = LogFactory.getLog(WxAuthController.class);

    @Autowired
    private LitemallUserService userService;

    @Autowired
    private WxMaService wxService;

    @Autowired
    private NotifyService notifyService;

    @Autowired
    private CouponAssignService couponAssignService;
    @Autowired
    private LitemallMessageService messageService;
    //某个上级的下面所有子类人数
    private static Integer regNum =0;
    //某个上级的子类
    private static List<LitemallUser> myTeam = new ArrayList<LitemallUser>();
    /**
     * 账号登录
     *
     *
     * @param user2 请求对象
     * @return 登录结果
     */
    @PostMapping("login")
    public Object login(@RequestBody LitemallUser user2) {
//        String username = JacksonUtil.parseString(body, "username");
//        String password = JacksonUtil.parseString(body, "password");
        if (user2.getUsername()== null || user2.getPassword() == null) {
            return ResponseUtil.badArgument();
        }

        List<LitemallUser> userList = userService.queryByUsername(user2.getUsername());
        LitemallUser user = null;
        if (userList.size() > 1) {
            return ResponseUtil.serious();
        } else if (userList.size() == 0) {
            return ResponseUtil.badArgumentValue();
        } else {
            user = userList.get(0);
        }

        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
        if (!encoder.matches(user2.getPassword(), user.getPassword())) {
            return ResponseUtil.fail(AUTH_INVALID_ACCOUNT, "账号密码不对");
        }

        // userInfo
        UserInfo userInfo = new UserInfo();
        userInfo.setNickName(user2.getUsername());
        userInfo.setAvatarUrl(user.getAvatar());
        userInfo.setUserLevel(user.getUserLevel());
        userInfo.setId(user.getId());

        // token
        UserToken userToken = UserTokenManager.generateToken(user.getId());

        Map<Object, Object> result = new HashMap<Object, Object>();
        result.put("token", userToken.getToken());
        result.put("tokenExpire", userToken.getExpireTime().toString());
        result.put("userInfo", userInfo);
        return ResponseUtil.ok(result);
    }

    /**
     * 微信登录
     *
     * @param wxLoginInfo 请求内容，{ code: xxx, userInfo: xxx }
     * @param request     请求对象
     * @return 登录结果
     */
    @PostMapping("login_by_weixin")
    public Object loginByWeixin(@RequestBody WxLoginInfo wxLoginInfo, HttpServletRequest request) {
        String code = wxLoginInfo.getCode();
        UserInfo userInfo = wxLoginInfo.getUserInfo();
        if (code == null || userInfo == null) {
            return ResponseUtil.badArgument();
        }

        String sessionKey = null;
        String openId = null;
        try {
            WxMaJscode2SessionResult result = this.wxService.getUserService().getSessionInfo(code);
            sessionKey = result.getSessionKey();
            openId = result.getOpenid();
        } catch (Exception e) {
            e.printStackTrace();
        }

        if (sessionKey == null || openId == null) {
            return ResponseUtil.fail();
        }

        LitemallUser user = userService.queryByOid(openId);
        if (user == null) {
            user = new LitemallUser();
            user.setUsername(openId);
            user.setPassword(openId);
            user.setWeixinOpenid(openId);
            user.setAvatar(userInfo.getAvatarUrl());
            user.setNickname(userInfo.getNickName());
            user.setGender(userInfo.getGender());
            user.setUserLevel((byte) 0);
            user.setStatus((byte) 0);
            user.setLastLoginTime(LocalDateTime.now());
            user.setLastLoginIp(IpUtil.client(request));

            userService.add(user);

            // 新用户发送注册优惠券
            couponAssignService.assignForRegister(user.getId());
        } else {
            user.setLastLoginTime(LocalDateTime.now());
            user.setLastLoginIp(IpUtil.client(request));
            if (userService.updateById(user) == 0) {
                return ResponseUtil.updatedDataFailed();
            }
        }

        // token
        UserToken userToken = UserTokenManager.generateToken(user.getId());
        userToken.setSessionKey(sessionKey);

        Map<Object, Object> result = new HashMap<Object, Object>();
        result.put("token", userToken.getToken());
        result.put("tokenExpire", userToken.getExpireTime().toString());
        result.put("userInfo", userInfo);
        return ResponseUtil.ok(result);
    }


    /**
     * 请求验证码
     *
     * @param body 手机号码{mobile}
     * @return
     */
    @PostMapping("regCaptcha")
    public Object registerCaptcha(@RequestBody String body) {
        String phoneNumber = JacksonUtil.parseString(body, "mobile");
        if (StringUtils.isEmpty(phoneNumber)) {
            return ResponseUtil.badArgument();
        }
        if (!RegexUtil.isMobileExact(phoneNumber)) {
            return ResponseUtil.badArgumentValue();
        }

        if (!notifyService.isSmsEnable()) {
            return ResponseUtil.fail(AUTH_CAPTCHA_UNSUPPORT, "小程序后台验证码服务不支持");
        }
        String code = CharUtil.getRandomNum(6);
        notifyService.notifySmsTemplate(phoneNumber, NotifyType.CAPTCHA, new String[]{code});

        boolean successful = CaptchaCodeManager.addToCache(phoneNumber, code);
        if (!successful) {
            return ResponseUtil.fail(AUTH_CAPTCHA_FREQUENCY, "验证码未超时1分钟，不能发送");
        }

        return ResponseUtil.ok();
    }

    /**
     * 账号注册
     *
     * @param body    请求内容
     *                {
     *                username: xxx,
     *                password: xxx,
     *                mobile: xxx
     *                code: xxx
     *                }
     *                其中code是手机验证码，目前还不支持手机短信验证码
     * @param request 请求对象
     * @return 登录结果
     * 成功则
     * {
     * errno: 0,
     * errmsg: '成功',
     * data:
     * {
     * token: xxx,
     * tokenExpire: xxx,
     * userInfo: xxx
     * }
     * }
     * 失败则 { errno: XXX, errmsg: XXX }
     */
    @PostMapping("register")
    public Object register(@RequestBody String body, HttpServletRequest request) {
        String username = JacksonUtil.parseString(body, "username");
        String password = JacksonUtil.parseString(body, "password");
        String mobile = JacksonUtil.parseString(body, "mobile");
//        String code = JacksonUtil.parseString(body, "code");
//        String wxCode = JacksonUtil.parseString(body, "wxCode");

        /*if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password) || StringUtils.isEmpty(mobile)
                || StringUtils.isEmpty(wxCode) || StringUtils.isEmpty(code)) {
            return ResponseUtil.badArgument();
        }*/
        if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password) || StringUtils.isEmpty(mobile)) {
            return ResponseUtil.badArgument();
        }
        List<LitemallUser> userList = userService.queryByUsername(username);
        if (userList.size() > 0) {
            return ResponseUtil.fail(AUTH_NAME_REGISTERED, "用户名已注册");
        }

        userList = userService.queryByMobile(mobile);
        if (userList.size() > 0) {
            return ResponseUtil.fail(AUTH_MOBILE_REGISTERED, "手机号已注册");
        }
        if (!RegexUtil.isMobileExact(mobile)) {
            return ResponseUtil.fail(AUTH_INVALID_MOBILE, "手机号格式不正确");
        }
        //判断验证码是否正确
       /* String cacheCode = CaptchaCodeManager.getCachedCaptcha(mobile);
        if (cacheCode == null || cacheCode.isEmpty() || !cacheCode.equals(code)) {
            return ResponseUtil.fail(AUTH_CAPTCHA_UNMATCH, "验证码错误");
        }*/

        /*String openId = null;
        try {
            WxMaJscode2SessionResult result = this.wxService.getUserService().getSessionInfo(wxCode);
            openId = result.getOpenid();
        } catch (Exception e) {
            e.printStackTrace();
            return ResponseUtil.fail(AUTH_OPENID_UNACCESS, "openid 获取失败");
        }
        userList = userService.queryByOpenid(openId);
        if (userList.size() > 1) {
            return ResponseUtil.serious();
        }
        if (userList.size() == 1) {
            LitemallUser checkUser = userList.get(0);
            String checkUsername = checkUser.getUsername();
            String checkPassword = checkUser.getPassword();
            if (!checkUsername.equals(openId) || !checkPassword.equals(openId)) {
                return ResponseUtil.fail(AUTH_OPENID_BINDED, "openid已绑定账号");
            }
        }*/

        LitemallUser user = null;
        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
        String encodedPassword = encoder.encode(password);
        user = new LitemallUser();
        user.setUsername(username);
        user.setPassword(encodedPassword);
        user.setMobile(mobile);
//        user.setWeixinOpenid(openId);
        //user.setAvatar("https://yanxuan.nosdn.127.net/80841d741d7fa3073e0ae27bf487339f.jpg?imageView&quality=90&thumbnail=64x64");
        user.setNickname(username);
        user.setGender((byte) 0);
        user.setUserLevel((byte) 0);
        user.setStatus((byte) 0);
        user.setLastLoginTime(LocalDateTime.now());
        user.setLastLoginIp(IpUtil.client(request));
        userService.add(user);

        // 给新用户发送注册优惠券
//        couponAssignService.assignForRegister(user.getId());

        // userInfo
        UserInfo userInfo = new UserInfo();
        userInfo.setNickName(username);
        userInfo.setAvatarUrl(user.getAvatar());

        // token
        //UserToken userToken = UserTokenManager.generateToken(user.getId());

        Map<Object, Object> result = new HashMap<Object, Object>();
        /*result.put("token", userToken.getToken());
        result.put("tokenExpire", userToken.getExpireTime().toString());*/
        result.put("userInfo", userInfo);
        return ResponseUtil.ok(result);
    }

    /**
     * 账号密码重置
     *
     * @param body    请求内容
     *                {
     *                password: xxx,
     *                mobile: xxx
     *                code: xxx
     *                }
     *                其中code是手机验证码，目前还不支持手机短信验证码
     * @param request 请求对象
     * @return 登录结果
     * 成功则 { errno: 0, errmsg: '成功' }
     * 失败则 { errno: XXX, errmsg: XXX }
     */
    @PostMapping("reset")
    public Object reset(@RequestBody String body, HttpServletRequest request) {
        String password = JacksonUtil.parseString(body, "password");
        String mobile = JacksonUtil.parseString(body, "mobile");
        String code = JacksonUtil.parseString(body, "code");

        if (mobile == null || code == null || password == null) {
            return ResponseUtil.badArgument();
        }

        //判断验证码是否正确
        String cacheCode = CaptchaCodeManager.getCachedCaptcha(mobile);
        if (cacheCode == null || cacheCode.isEmpty() || !cacheCode.equals(code))
            return ResponseUtil.fail(AUTH_CAPTCHA_UNMATCH, "验证码错误");

        List<LitemallUser> userList = userService.queryByMobile(mobile);
        LitemallUser user = null;
        if (userList.size() > 1) {
            return ResponseUtil.serious();
        } else if (userList.size() == 0) {
            return ResponseUtil.fail(AUTH_MOBILE_UNREGISTERED, "手机号未注册");
        } else {
            user = userList.get(0);
        }

        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
        String encodedPassword = encoder.encode(password);
        user.setPassword(encodedPassword);

        if (userService.updateById(user) == 0) {
            return ResponseUtil.updatedDataFailed();
        }

        return ResponseUtil.ok();
    }

    @PostMapping("bindPhone")
    public Object bindPhone(@LoginUser Integer userId, @RequestBody String body) {
        String sessionKey = UserTokenManager.getSessionKey(userId);
        String encryptedData = JacksonUtil.parseString(body, "encryptedData");
        String iv = JacksonUtil.parseString(body, "iv");
        WxMaPhoneNumberInfo phoneNumberInfo = this.wxService.getUserService().getPhoneNoInfo(sessionKey, encryptedData, iv);
        String phone = phoneNumberInfo.getPhoneNumber();
        LitemallUser user = userService.findById(userId);
        user.setMobile(phone);
        if (userService.updateById(user) == 0) {
            return ResponseUtil.updatedDataFailed();
        }
        return ResponseUtil.ok();
    }

    @PostMapping("logout")
    public Object logout(@LoginUser Integer userId) {
        if (userId == null) {
            return ResponseUtil.unlogin();
        }
        UserTokenManager.removeToken(userId);
        return ResponseUtil.ok();
    }
    /**
     *帮助注册
     */
    @PostMapping("memberRegist")
    public Object memberRegist(@RequestBody LitemallUser user){
        if(user == null || "".equals(user.getUsername()) || "".equals(user.getRecommendcode()) || "".equals(user.getPassword())){
            return ResponseUtil.fail(-1,"用户信息不能为空！");
        }
        //给钱一星步骤默认已经支付成功,暂时不做
        if(userService.checkByUsername(user.getUsername())){
            LitemallUser memberUser = userService.findByUserName(user.getUsername());
            BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
            if (!encoder.matches(user.getPassword(), memberUser.getPassword())) {
                return ResponseUtil.fail(AUTH_INVALID_ACCOUNT, "账号密码不对");
            }else{
                LitemallUser superUser = userService.queryByRecomendcode(user.getRecommendcode());
                if(superUser == null){
                    return  ResponseUtil.fail(-1,"推荐码不正确！");
                }else{
                    if(!"".equals(memberUser.getRecommendcode()) && memberUser.getRecommendcode() !=null || memberUser.getParentid() != null){
                        return  ResponseUtil.fail(-1,"该用户是星级会员");
                    }
                    superUser.setRegistnum(superUser.getRegistnum()+1);
                    userService.updateFatherById(superUser);
                }
                //上级用户id
                int userId = 0;
                //获取parentID
                if(superUser.getUserLevel() >= 5){
                    userId = superUser.getId();
                }else{
                    userId = superUser.getFivestartid();
                }
                //获取推荐码
               String recommendCode= GeneratorUIDTools.toSerialCode(memberUser.getId());
                userService.updateByName(superUser.getId(), user.getUsername(),recommendCode);
                //给5星添加审核消息
                messageService.insertMessage(memberUser.getId(),userId,0,0,"");
            }
        }else{
            return ResponseUtil.fail(-1,"该用户不存在！");
        }
        return ResponseUtil.ok();
    }
    /**
     * 审核升级
     * @return  审核提示
     */
    @GetMapping("auditing")
    public Object auditing (@RequestParam Integer commitId,@RequestParam Integer status){
        if (commitId == null || status == null){
            return ResponseUtil.fail(-1,"ID为空或状态空！");
        }
        LitemallUser user =userService.findById(commitId);
        LitemallMessage message = new LitemallMessage();
        message.setAuditstate(status);
        message.setCommitid(commitId);
        int msgNum = messageService.updateMessage(message);
        //1为同意，0为拒绝
        if(status == 1){
            if(user.getUserLevel() == 4){
                messageService.insertMessage(commitId,user.getNinestartid(),user.getUserLevel(),1,"");
            }
            LitemallUser lmuser = userService.findById(commitId);
            int userNum = userService.updateById(lmuser);
        }

        return ResponseUtil.ok();
    }
//    @Scheduled(cron = "0 */1 * * * *")
//            public Object isAudite(){
//                System.out.println("每小时执行一次");
//                List<LitemallMessage> message = messageService.findMessageByStatus();
//                LitemallUser user  = new LitemallUser();
//                if (message == null){
//                    System.out.println("暂无没审核消息");
//                }
//                for (LitemallMessage obj: message) {
//                    Long end = LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant().getEpochSecond();
//                    Long  start = obj.getCreatetime().atZone(ZoneId.systemDefault()).toInstant().getEpochSecond();
//                    Long res = end-start;
//
//                    if(res>=60){
//                        user=userService.findById(obj.getUserid());
//                        user.setMoney(user.getMoney()+1);
//                        userService.updateMoneyById(user);
//                        messageService.insertMessage(obj.getCommitid(),1,(byte)1,2,"");
//                        messageService.deleteMessageByUserId(obj.getUserid());
//                        System.out.println("----****"+user.getUsername()+"没有审核"+"****---");
//                    }
//
//        }
//        return ResponseUtil.ok();
//    }
    /**
     * 审核消息列表
     * @return 审核消息列表
     */
    @GetMapping("auditingList")
    public Object auditingList (@RequestParam Integer userId){
        if (userId == null){
            return ResponseUtil.fail(-1,"用户ID为空！");
        }
        List<MessageVo> data =messageService.findMessageByUserId(userId);

        return ResponseUtil.ok(data);
    }

    /**
     * 我的消息
     * @param username
     * @return
     */
    @GetMapping("myMessge")
    public Object myMessage(@RequestParam String username){
        if("".equals(username)){
            return ResponseUtil.fail(-1,"用户名为空");
        }
        LitemallUser user = userService.findByUserName(username);
        List<MessageVo> data = messageService.selectByCommitId(user.getId());
        return ResponseUtil.ok(data);
    }
    /**
     * 一直获取注册数，直到注册数为0
     */
    public Integer getRegistNum(LitemallUser user){

            List<LitemallUser> lmUser = userService.findByParentId(user.getId());
            if(lmUser==null || lmUser.size() ==0){
                return 0;
            }
            System.out.println("长度："+lmUser.size());
            for (int j =0;j<lmUser.size();j++){
                if(lmUser.get(j).getRegistnum()>0){
                    ++regNum;
                    getRegistNum(lmUser.get(j));
                }else{
                    regNum++;
                }
            }
            return regNum;
    }
    /**
     * 申请升星
     * @param username
     * @return
     */
    @GetMapping("upStar")
    public Object upStar(@RequestParam String username){

        if("".equals(username)){
            return ResponseUtil.fail(-1,"用户名为空");
        }
        //获取用户等级
        LitemallUser user = userService.findByUserName(username);
        if(user.getUserLevel()>=9){
            return ResponseUtil.fail(-1,"用户已达顶级");
        }
        //获取用户上级id，根据上级id获取上级的等级

        LitemallUser upUser = userService.findById(user.getParentid());
        //判断用户的注册数是否达到3^(等级数)
       /* RegistNumUtil regUtil =new RegistNumUtil();
        Integer num = regUtil.getRegistNum(user);*/
        Integer num = getRegistNum(user);
        System.out.println("注册数:"+num);
        if(num == Math.pow(3,user.getUserLevel())){
            regNum = 0;
            if(upUser != null){
                //判断用户等级等于上级等级
                if(user.getUserLevel() == upUser.getUserLevel()){
                    //根据上级用户id获取上级用户的parentid发一条消息给上级的父类
                    messageService.insertMessage(user.getId(),upUser.getParentid(),user.getUserLevel(),1,"");
                    LitemallUser superUser = userService.findById(upUser.getParentid());
                    messageService.insertMessage(user.getId(),0,user.getUserLevel(),null,"这是你的新上级微信号："+superUser.getMobile()+"和名字："+superUser.getUsername());
                }else{
                    if(upUser.getMoney()>=3){
                        List<LitemallUser> users = userService.findByParentId(user.getParentid());
                        int index =(int)Math.random()*(users.size()-1)+1;
                        LitemallUser waitUser = new LitemallUser();
                        while (true){
                            waitUser=users.get(index);
                            if(waitUser.getId() == upUser.getId()){
                                index =(int)Math.random()*(users.size()-1)+1;
                            }else{
                                break;
                            }

                        }
                        userService.updateParentById(user,waitUser.getId());
                        messageService.insertMessage(user.getId(),0,user.getUserLevel(),null,"这是您新的上级微信号："+waitUser.getMobile()+"和名字："+waitUser.getUsername()+"原本上级已被拉黑");
                    }
                    messageService.insertMessage(user.getId(),upUser.getId(),user.getUserLevel(),1,"");
                }
            }
        }else{
            regNum =0;
           return ResponseUtil.fail(-1,"注册数不够");
        }
        return ResponseUtil.ok();
    }

    /**
     * 我的团队
     * @param username
     * @return
     */
    @GetMapping("myTeam")
    public Object myTeam(@RequestParam String username){
        LitemallUser user = userService.findByUserName(username);
        myTeam.clear();
        getMyTeam(user);
        if(myTeam == null){
            return ResponseUtil.fail(-1,"暂无队员");
        }
        return ResponseUtil.ok(myTeam);
    }
    public void getMyTeam(LitemallUser user){
        List<LitemallUser> userList = userService.findByParentId(user.getId());
        if(userList.size()<= 0){
            return;
        }
        for(int i =0;i<userList.size();i++){
            if(userList.get(i) !=null && !userList.isEmpty()){
                myTeam.add(userList.get(i));
                getMyTeam(userList.get(i));
            }
        }
    }
    @GetMapping("userInfo")
    public Object userInfo(@RequestParam String username){
        if("".equals(username)){
            return ResponseUtil.fail(-1,"用户为空");
        }
        LitemallUser data = userService.findByUserName(username);
        if(data == null){
            return ResponseUtil.fail(-1,"信息被狼叼走了");
        }
        return ResponseUtil.ok(data);
    }
}
